﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using QxFramework.Core;

public class BulletManager : LogicModuleBase, IBulletManager
{
    public string Path = "Prefabs/Bullet/";
    List<BulletData> bulletDatas;

    public override void Init()
    {
        base.Init();
        bulletDatas = new List<BulletData>();
    }

    // Update is called once per frame
    public override void Update()
    {
        base.Update();
    }

    public void DestroyBullet(BulletData bullet)
    {
        GameObject.Destroy(bullet.Bullet);
        bulletDatas.Remove(bullet);
    }

    public void InputBulletData(BulletData bullet)
    {
        bulletDatas.Add(bullet);
    }

    public List<BulletData> OutputData()
    {
        return bulletDatas;
    }

    /// <summary>
    /// 生成环形弹幕。
    /// </summary>
    /// <param name="path">子弹在Resouces/Prefabs/Items/Bullets/文件夹的路径。</param>
    /// <param name="pos">生成子弹的中心位置</param>
    /// <param name="dir">生成方向</param>
    /// <param name="angle">生成子弹的散射角度</param>
    /// <param name="num">子弹数量</param>
    /// <param name="damage">伤害</param>
    /// <param name="radius">环形弹幕的半径</param>
    /// <param name="interval">生成弹幕的间隔时间</param>
    public void InstantiateBullets(string path, Vector3 pos, Vector2 dir, float angle, int num, float damage, float radius = 0, float interval = 0, List<BulletMotion> bulletMotions = null)
    {
        CoroutineTool.Instance.StartCoroutine(Instantiate(path, pos, dir, angle, num, damage, radius, interval, bulletMotions));
    }

    public IEnumerator Instantiate(string path, Vector3 pos, Vector2 dir, float angle, int num, float damage, float radius, float interval, List<BulletMotion> bulletMotions = null)
    {
        if (num == 1)
        {
            GameObject bullet = ResourceManager.Instance.Instantiate(Path + path);
            bullet.transform.position = pos + new Vector3((dir.normalized * radius).x, (dir.normalized * radius).y, 0);
            bullet.GetComponent<BulletMotionController>().towards = dir;
            bullet.GetComponent<BulletMotionController>().AddMotion(bulletMotions);
            BulletData bulletData = bullet.GetComponent<Bullet>().bulletData;
            bulletData.Damage = damage;
        }
        else if (num > 1)
        {   
            float theta = dir.y > 0 ? Vector2.Angle(dir, Vector2.right) : (360 - Vector2.Angle(dir, Vector2.right));
            for (int i = 0; i < num; i++)
            {
                float offsetAngle = (theta - angle / 2 + i * angle / (num - 1)) * Mathf.PI / 180;
                Vector2 offset = new Vector2(Mathf.Cos(offsetAngle), Mathf.Sin(offsetAngle));
                GameObject bullet = ResourceManager.Instance.Instantiate(Path + path);
                bullet.transform.position = pos + new Vector3((offset * radius).x, (offset * radius).y, 0);
                bullet.GetComponent<BulletMotionController>().towards = offset;
                bullet.GetComponent<BulletMotionController>().AddMotion(bulletMotions);
                BulletData bulletData = bullet.GetComponent<Bullet>().bulletData;
                bulletData.Damage = damage;
                yield return new WaitForSeconds(interval);
            }
        }
        else
        {
            yield break;
        }
    }

    /// <summary>
    /// 生成直线弹幕
    /// </summary>
    /// <param name="path">子弹在Resource文件夹的路径。</param>
    /// <param name="pos">生成子弹的起始位置。</param>
    /// <param name="spawnDir">向哪个方向生成子弹。注意：这个向量包含距离信息。</param>
    /// <param name="moveDir">子弹朝向哪个方向</param>
    /// <param name="num">生成子弹的数量</param>
    /// <param name="damage">伤害</param>
    /// <param name="interval">生成弹幕的间隔时间</param>
    public void InstantiateBullets(string path, Vector3 pos, Vector2 spawnDir, Vector2 moveDir, int num, float damage, float interval = 0, List<BulletMotion> bulletMotions = null)
    {
        CoroutineTool.Instance.StartCoroutine(Instantiate(path, pos, spawnDir, moveDir, num, damage, interval, bulletMotions));
    }

    public IEnumerator Instantiate(string path, Vector3 pos, Vector2 spawnDir, Vector2 moveDir, int num, float damage, float interval, List<BulletMotion> bulletMotions = null)
    {
        if (num == 1)
        {
            GameObject bullet = ResourceManager.Instance.Instantiate(Path + path);
            bullet.transform.position = pos;
            bullet.GetComponent<BulletMotionController>().towards = moveDir;
            bullet.GetComponent<BulletMotionController>().AddMotion(bulletMotions);
            BulletData bulletData = bullet.GetComponent<Bullet>().bulletData;
            bulletData.Damage = damage;
        }
        else if (num > 1)
        {   
            for (int i = 0; i < num; i++)
            {
                GameObject bullet = ResourceManager.Instance.Instantiate(Path + path);
                bullet.transform.position = pos + (Vector3)(spawnDir * i / (num - 1));
                bullet.GetComponent<BulletMotionController>().towards = moveDir;
                bullet.GetComponent<BulletMotionController>().AddMotion(bulletMotions);
                BulletData bulletData = bullet.GetComponent<Bullet>().bulletData;
                bulletData.Damage = damage;
                yield return new WaitForSeconds(interval);
            }
        }
        else
        {
            yield break;
        }
    }
}

public class BulletData : GameDataBase
{
    public bool IsFromPlayer;
    public Vector2 InitialPosition;
    public float Speed;
    public Vector2 Direction;
    public float Range;
    public float Damage;
    public float Distance;
    public GameObject Bullet;
}